<?php
require_once 'UE/DB/Abstract.php';

/**
 * 使用 MYSQL 扩展
 *
 * ============================================================================
 * 版权所有: (c) 2009-2011，<UEShop Inc>，并保留所有权利。
 * 网站地址: http://www.ueshop.cn
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 *
 * @author      cmpan
 * @copyright   Copyright (c) 2009-2011 UEShop Inc. (http://www.ueshop.cn)
 * @license     http://www.ueshop.cn/1_0.txt
 */

class UE_DB_Mysql extends UE_DB_Abstract {

	/**
	 * 数据库连接
	 *
	 */
	public function __construct() {
		try {
			if(!$this->_link = @mysql_connect(UE_Config::get('db_host'), UE_Config::get('db_user'), UE_Config::get('db_pass'))) {
				throw new UE_DB_Exception(UE_Lang::get('ue.db.connerror'));
			}
			/* 设置Mysql字符集 */
			if($this->version() > '4.1') {
				mysql_query("SET NAMES utf8", $this->_link);
				if($this->version() > '5.0.1') {
					mysql_query("SET sql_mode=''", $this->_link);
				}
			}
			/* 选择数据库 */
			if(!$this->selectDB(UE_Config::get('db_name'))) {
				throw new UE_DB_Exception(sprintf(UE_Lang::get('ue.db.connerror'), UE_Config::get('db_name')));
			}
		} catch (UE_DB_Exception $e) {
			print $e->__toString();
		}
	}

	/**
	 *  获取MySQL版本
	 *
	 * @return string
	 */
	public function version() {
		return mysql_get_server_info($this->_link);
	}

	/**
	 * 选择数据库
	 *
	 * @param string $db
	 */
	public function selectDB($db = '') {
		$db or die(UE_Lang::get('ue.db.dbnameEmpty'));
		$this->_db = $db;
		if(! mysql_select_db($db, $this->_link)) {
			throw new UE_DB_Exception(sprintf(UE_Lang::get('ue.db.dbNotExists'), UE_Config::get('db_name')) . $this->errMsgs());
		}
		return true;
	}

	/**
	 * 简单查询
	 *
	 * @param String $sql
	 * @param const $type
	 * @return mixed
	 */
	public function query($sql) {
		//print "$sql\n";
		$sql = $this->prefix($sql);
		$query = mysql_query($sql, $this->_link);
		$this->execNums++;
		if(false === $query) {
			$msg = "[debug msg] :" . UE_Lang::get('ue.db.queryError') . $this->errMsgs();
			if(UE_Config::get('debug')) $msg .= " SQL: <pre>\r\n" . $sql . "\r\n</pre>";
			throw new UE_DB_Exception($msg);
		}
		return $query;
	}

	/**
	 * 读取一行
	 *
	 * @param String $sql
	 * @param bool $allowCache 是否允许启用缓存 UE_Config::get('db_cache') 起作用后才有用
	 * @return array $row  结果记录集
	 */
	public function getOne($sql, $allowCache = 0) {
		$row = array();
		if ($allowCache && UE_Config::get('db_cache')) {
		    $id = md5($sql);
		    $key = "query/{$id[0]}{$id[1]}/$id";
		    if(!$row = UE_Cache::createCache()->get($key)) {
		    	$query = $this->query($sql);
	    		if($query) {
	    			$row = mysql_fetch_array($query, MYSQL_ASSOC);
	    		}
	    		
	    		UE_Cache::createCache()->set($key, $row);	    		
		    }
					
			if ($row) {
				return $row;
			}
			
			return false;
		} else {    		
    		$query = $this->query($sql);
    		if($query) {
    			$row = mysql_fetch_array($query, MYSQL_ASSOC);
    		}
    		return $row;
		}
	}

	/**
	 * 读取所有行
	 *
	 * @param String $sql
	 * @param bool $allowCache 是否允许启用缓存 UE_Config::get('db_cache') 起作用后才有用
	 * @return array $rows  结果记录集
	 */
	public function getAll($sql, $allowCache = 0) {
		$rows = array();
		if ($allowCache && UE_Config::get('db_cache')) {
		    $id = md5($sql);
		    $key = "query/{$id[0]}{$id[1]}/$id";
		    if(!$rows = UE_Cache::createCache()->get($key)) {
		    	$query = $this->query($sql);
	    		while($row = mysql_fetch_array($query, MYSQL_ASSOC)) {
	    			$rows[] = $row;
	    		}
	    		
	    		UE_Cache::createCache()->set($key, $rows);	    		
		    }
		    return $rows;
		} 
		 
		$query = $this->query($sql);
		while($row = mysql_fetch_array($query, MYSQL_ASSOC)) {
			$rows[] = $row;
		}
		return $rows;		
	}

	/**
	 * 取得前一次 MySQL 操作所影响的记录行数
	 *
	 * @return int 行数
	 */
	public function affectedRows() {
		return mysql_affected_rows($this->_link);
	}

	/**
	 * 取得结果集中行的数目
	 *
	 * @param String $query
	 * @return int 行数
	 */
	public function numRows($sql) {
		$query = $this->query($sql);
		$rows = mysql_num_rows($query);
		return $rows;
	}

	/**
	 * 释放MySQL结果内存
	 * 仅需要在考虑到返回很大的结果集时会占用多少内存时调用。
	 * 在脚本结束后所有关联的内存都会被自动释放。
	 *
	 * @param resource $resource 
	 * @return bool
	 */
	public function freeResult(&$resource) {
		return mysql_free_result($resource);
	}

	/**
	 * 取得上一步 INSERT 操作产生的 ID
	 *
	 * @return int $id
	 */
	public function lastInsertId() {
		return mysql_insert_id($this->_link);
	}

	/**
	 * 关闭数据库
	 *
	 * @return
	 */
	public function close() {
		return mysql_close($this->_link);
	}

	/**
	 * 更新一行或多行
	 *
	 * @param string $table 要更新的表
	 * @param string $key  更新参照的字段名
	 * @param string $value 更新参照的字段值
	 * @param array $array 更新的数据array('字段'=>'值'[,...])
	 * @param int $limit 更新多少条，默认全部更新对应的列
	 * @return bool
	 */
	public function update($table, $key, $value, $array, $limit = 0) {
		if(! is_array($array)) {
			throw new UE_DB_Exception('The second param must be array');
		}
		// 获取表的结构
		$fields = array();
		$structure = $this->getAll("SHOW COLUMNS FROM $table");
		foreach ($structure as $field) {
			$fields[] = $field['Field'];
		}
		
		$temp = array();
		// 取表中存在的字段
		foreach($array as $k => $v) {
			if (!in_array($k, $fields)) {
				continue;
			}
			$k = trim($k);
			$temp[] = "`$k` = '$v'";
		}
		$sets = join(',', $temp);
		$sql = "UPDATE `$table` SET $sets WHERE `$key` = '$value'";
		$limit && $sql .= " LIMIT $limit";
		
		return $this->query($sql);
	}

	/**
	 * 插入一条记录
	 *
	 * @param string $table
	 * @param array $array
	 * @return bool
	 */
	public function insertRow($table, $array) {
		if(! is_array($array)) {
			throw new UE_DB_Exception('The second param must be array');
		}
		
		// 获取表的结构
		$fields = array();
		$structure = $this->getAll("SHOW COLUMNS FROM $table");
		foreach ($structure as $field) {
			$fields[] = $field['Field'];
		}
		
		$temp = array();
		foreach($array as $k => $v) {
			if (!in_array($k, $fields)) {
				continue;
			}
			$temp[] = "`$k` = '$v'";
		}
		$sets = join(',', $temp);
		$sql = "INSERT INTO `$table` SET $sets";
		if($this->query($sql)) {
			return $this->lastInsertId();
		}
		return false;
	}

	/**
	 * 删除一行或多行
	 *
	 * @param string $table  表名
	 * @param string $key  条件的列名
	 * @param string $value 条件的值
	 * @param int $limit 删除多少行
	 * @return bool
	 */
	public function delete($table, $key, $value, $limit = 0) {
		$sql = "DELETE FROM `$table` WHERE `$key` = '$value'";
		$limit && $sql .= " LIMITE $limit";
		//print $sql;exit;
		return $this->query($sql);
	}

	public function errMsgs() {
		return " error:" . mysql_error() . "\nno:" . mysql_errno();
	}
	
	/**
	 * 获取最近的错误信息
	 *
	 * @return string
	 */
	public function getLastErr() {
		return " error:" . mysql_error() . "\nno:" . mysql_errno();
	}
	
	/**
	 * SHOW COLUMNS FROM `my_table`
	 * 
	 * @param string $table  表名
	 * @param string $db     数据库名，如果为空则选择当前使用的数据库
	 */
	public function getTableInfo($table, $db = '') {
		empty($db) && $db = $this->_db;
		return $this->getAll("SHOW FULL COLUMNS FROM $db.$table");
	}
	
	/**
	 * 获取查询结果的第一行第一列的值
	 *
	 * @param string $sql
	 * @return string|number
	 */
	public function getFirstField($sql, $allowCache = false) {
		if ($allowCache && UE_Config::get('db_cache')) {
			$id = md5($sql);
		    $key = "query/{$id[0]}{$id[1]}/$id";
		    if(false === ($row = UE_Cache::createCache()->get($key))) {
		    	$query = $this->query($sql);
	    		if($query) {
	    			$row = mysql_fetch_row ($query);
	    		}
	    		
	    		UE_Cache::createCache()->set($key, $row);	    		
		    }
					
			if ($row) {
				return $row[0];
			}
			
			return false;
		}
		
		$query = $this->query($sql);
		if($query) {
			$row = mysql_fetch_row ($query);
			if ($row) {
				return $row[0];
			}
		}
		return false;
	}
}

